#ifndef GST_GOCAD_VOXET_PARSER_HPP
#define GST_GOCAD_VOXET_PARSER_HPP

#include <buildspec.h>

#include "GSTenums.h"

#include <iosfwd>
#include <string>
#include <vector>

#include <boost/cstdint.hpp>
#include <boost/optional.hpp>

namespace GST
{
namespace Parsers
{
namespace GocadParser
{
// workaround for OpenGeometryFiles::run (strange things are happening there)
// TODO: think of something better here
// probably best to refactor this parser into the other Gocad parser
struct WrongObjectTypeException
{
};
struct ObjectMetaData
{
	std::string name;
};
struct CoordinateSystemMetaData
{
	enum Zpositive
	{
		depth,
		elevation
	};
	Zpositive zpositive;
	CoordinateSystemMetaData() : zpositive(elevation)
	{
	}
};

struct FloatVec
{
	float x;
	float y;
	float z;
};

struct IntVec
{
	int u;
	int v;
	int w;
};

struct VoxetAxisMetadata
{
	FloatVec axisO;
	FloatVec axisU;
	FloatVec axisV;
	FloatVec axisW;
	FloatVec axisMin;
	FloatVec axisMax;
	IntVec axisN;
};

struct VoxetFlagsMetadata
{
	std::string flagsFile;
	boost::int64_t arrayLength;
	int bitLength;
	int esize;
	boost::int64_t offset;
};

struct VoxetRegionMetadata
{
	std::string name;
	int posInFlags;
	VoxetRegionMetadata(const std::string &name, const int posInFlags)
		: name(name), posInFlags(posInFlags)
	{
	}
};

struct VoxetPropertyMetadata
{
	std::string name;
	std::string popertyFile;
	float noDataValue;
	boost::int64_t offset;
	int esize;
	boost::optional<std::string> interpolationMethod;
	boost::optional<std::string> storageType;
	boost::optional<int> isSigned;
	VoxetPropertyMetadata(const std::string &name,
						  const std::string &popertyFile,
						  const float noDataValue,
						  const boost::int64_t offset)
		: name(name)
		, popertyFile(popertyFile)
		, noDataValue(noDataValue)
		, offset(offset)
		, esize(4)
		, interpolationMethod()
		, storageType()
		, isSigned()
	{
	}

	VoxetPropertyMetadata(const std::string &name,
						  const std::string &popertyFile,
						  const float noDataValue,
						  const boost::int64_t offset,
						  int esize,
						  boost::optional<std::string> interpolationMethod,
						  boost::optional<std::string> storageType,
						  boost::optional<int> isSigned)
		: name(name)
		, popertyFile(popertyFile)
		, noDataValue(noDataValue)
		, offset(offset)
		, esize(esize)
		, interpolationMethod(interpolationMethod)
		, storageType(storageType)
		, isSigned(isSigned)
	{
	}
};

struct VoxetMetaData
{
	std::string metaDataFile;
	ObjectMetaData objectMetaData;
	CoordinateSystemMetaData coordinateSystemMetaData;
	VoxetAxisMetadata axisMetaData;
	VoxetFlagsMetadata flagsMetaData;
	std::vector<VoxetRegionMetadata> regionsMetaData;
	std::vector<VoxetPropertyMetadata> propertiesMetaData;
};

GST_API_EXPORT VoxetMetaData parseVoxetAsciiFile(const std::string &file);
GST_API_EXPORT VoxetMetaData parseVoxetAsciiFile(std::istream &is);
GST_API_EXPORT void normalizeMetaData(VoxetMetaData &metaData);

GST_API_EXPORT Geometry::PropertyTypes propertyTypeFromVoxetPropertyMetadata(
	const VoxetPropertyMetadata &voxetPropertyMetadata);

} // namespace GocadParser
} // namespace Parsers
} // namespace GST

#endif // GST_GOCAD_VOXET_PARSER_HPP
